package com.gzhryc.shared_device.pcl.code.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.IDeviceService;
import com.gzhryc.shared_device.common.device.dao.db.Device;
import com.gzhryc.shared_device.common.device.dao.db.DeviceProduceBatch;
import com.gzhryc.shared_device.common.device.dao.db.DeviceTypeFunc;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.common.device.services.dto.DeviceSearch;
import com.gzhryc.shared_device.pcl.code.PCLProduceConfig;
import com.gzhryc.shared_device.pcl.code.dao.ChargingCableDao;
import com.gzhryc.shared_device.pcl.code.dao.db.ChargingCable;
import com.gzhryc.shared_device.pcl.code.dao.db.PCLOrder;
import com.gzhryc.shared_device.pcl.code.dao.enums.ChargingCableEnum;
import com.gzhryc.shared_device.pcl.code.dao.enums.PCLOrderEnum;
import com.gzhryc.shared_device.pcl.code.services.dto.ChargingCableSearch;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class ChargingCableService implements IDeviceService {

    static Logger log = Logger.getLogger(ChargingCableService.class);

    public static ChargingCableService self() {
        return MultiDBTools.getService(ChargingCableService.class, true);
    }

    public static ChargingCableService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, ChargingCableService.class, true);
    }

    ChargingCableDao dao;

    public ChargingCableService(String jdbcKey) {
        dao = new ChargingCableDao(jdbcKey);
    }
    
    public List<ChargingCable> findJoinBySearch(ChargingCableSearch search) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("deviceSn",search.getDeviceSnList());
        conditions.and().is("device.user_id",search.getUserId());
        conditions.and().is("device.place_id",search.getPlaceId());
        conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
        if(search.getDeploy() != null){
            if(search.getDeploy()){
                conditions.and().isNotNull("device.place_id");
            }else{
                conditions.and().isNull("device.place_id");
            }
        }
        try {
            return dao.findJoinByCondition(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public List<ChargingCable> findJoinBySearch(ChargingCableSearch search, Integer pageNo, Integer pageLimit) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("deviceSn",search.getDeviceSnList());
        conditions.and().is("device.user_id",search.getUserId());
        conditions.and().is("device.place_id",search.getPlaceId());
        conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
        if(search.getDeploy() != null){
            if(search.getDeploy()){
                conditions.and().isNotNull("device.place_id");
            }else{
                conditions.and().isNull("device.place_id");
            }
        }
        try {
            return dao.findJoinByCondition(conditions, pageNo, pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public Long countJoinBySearch(ChargingCableSearch search) {
        Conditions conditions = dao.buildConditions(search);
        conditions.and().in("deviceSn",search.getDeviceSnList());
        conditions.and().is("device.user_id",search.getUserId());
        conditions.and().is("device.place_id",search.getPlaceId());
        conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
        if(search.getDeploy() != null){
            if(search.getDeploy()){
                conditions.and().isNotNull("device.place_id");
            }else{
                conditions.and().isNull("device.place_id");
            }
        }
        try {
            return dao.countJoin(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return 0L;
    }
    
    public List<ChargingCable> findByDeviceSnList(List<String> deviceSnList) {
		if (deviceSnList != null && deviceSnList.size() > 0) {
			Conditions conditions = new Conditions(ChargingCable.class);
			conditions.and().in("deviceSn", deviceSnList);
			try {
				return dao.findByCondition(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		return null;
	}

    public ChargingCable getByDeviceSn(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            Conditions conditions = new Conditions(ChargingCable.class);
            conditions.and().is("deviceSn", deviceSn);
            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public ChargingCable getJoinByDeviceSn(String deviceSn) {
        if (StringTools.isNotBlank(deviceSn)) {
            Conditions conditions = new Conditions(ChargingCable.class);
            conditions.and().is("deviceSn", deviceSn);
            try {
                return dao.getJoin(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public boolean add(ChargingCable chargingCable) throws LogicException {
        if (StringTools.isBlank(chargingCable.getProtocolType())) {
            throw new LogicException("设备协议不可以为空");
        }

        Device device = DeviceService.self().getByDeviceSn(chargingCable.getDeviceSn());
        if (device != null) {
            throw new LogicException("设备索引已存在");
        }

        chargingCable.setCreateDate(new Date());
        JdbcSession.begin();
        try {
            if (dao.insert(chargingCable) > 0) {
                device = new Device();
                device.setDeviceSn(chargingCable.getDeviceSn());
                device.setDeviceTypeId(chargingCable.getDeviceTypeId());
                device.setDeviceTypeName(chargingCable.getDeviceTypeName());
                if (DeviceService.self().add(device)) {
                    JdbcSession.commit();
                    return true;
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            JdbcSession.end();
        }
        return false;
    }

    public boolean produceDevice(DeviceProduceBatch produceBatch, DeviceTypeFunc deviceTypeFunc, PCLProduceConfig produceConfig){
        DeviceSearch search = new DeviceSearch();
        search.setBatchId(produceBatch.getBatchId());
        Integer pageNo = 1;
        Integer pageLimit = 300;
        List<Device> deviceList = DeviceService.self().findBySearch(search,pageNo,pageLimit);
        List<ChargingCable> data = new ArrayList<>();
        while (deviceList != null && deviceList.size() > 0){
            for(Device device : deviceList) {
                ChargingCable batteryCabinet = new ChargingCable();
                batteryCabinet.setDeviceSn(device.getDeviceSn());
                batteryCabinet.setDeviceTypeId(device.getDeviceTypeId());
                batteryCabinet.setDeviceTypeName(device.getDeviceTypeName());
                batteryCabinet.setPwdIndex("1");
                batteryCabinet.setSecretKey(produceConfig.getSecretKey());
                batteryCabinet.setProtocolType(deviceTypeFunc.getProtocolType());
                batteryCabinet.setCreateDate(new Date());
                data.add(batteryCabinet);
            }
            pageNo = pageNo + 1;
            deviceList = DeviceService.self().findBySearch(search,pageNo,pageLimit);
        }

        try {
            if(dao.insert(data) > 0){
                return true;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }

    public boolean toWorking(String deviceSn,String pwdIndex,String tradeNo,Date workDate){
        if(StringTools.isNotBlank(deviceSn) && StringTools.isNotBlank(pwdIndex)){
            ChargingCable updateEntity = new ChargingCable();
            updateEntity.setDeviceSn(deviceSn);
            updateEntity.setPwdIndex(pwdIndex);
            updateEntity.setState(ChargingCableEnum.State.Working.index());
            updateEntity.setCurrentTradeNo(tradeNo);
            updateEntity.setLastWorkDate(workDate);

            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean toFree(String deviceSn){
        if(StringTools.isNotBlank(deviceSn)){
            ChargingCable updateEntity = new ChargingCable();
            updateEntity.setDeviceSn(deviceSn);
            updateEntity.setState(ChargingCableEnum.State.Free.index());

            try {
                return dao.updateNotNull(updateEntity) > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    /**
     * 检查工作状态，耗时操作
     */
    public void checkWorkState(){
        Integer pageNo = 1;
        Integer pageLimit = 100;
        ChargingCableSearch search = new ChargingCableSearch();
        search.setState(ChargingCableEnum.State.Working.index());
        List<ChargingCable> chargingCableList = ChargingCableService.self().findJoinBySearch(search,pageNo,pageLimit);
        List<String> deviceSnList = new ArrayList<>();
        while (chargingCableList != null && chargingCableList.size() > 0){
            for(ChargingCable chargingCable : chargingCableList){
                if(StringTools.isNotBlank(chargingCable.getCurrentTradeNo())){
                    PCLOrder pclOrder = PCLOrderService.self(chargingCable.getLastWorkDate()).getByTradeNo(chargingCable.getCurrentTradeNo());
                    if(pclOrder == null || PCLOrderEnum.State.Finish.equals(chargingCable.getState()) || PCLOrderEnum.State.Close.equals(chargingCable.getState())) {
                        deviceSnList.add(chargingCable.getDeviceSn());
                    }
                }else{
                    deviceSnList.add(chargingCable.getDeviceSn());
                }
            }
            pageNo = pageNo + 1;
            chargingCableList = ChargingCableService.self().findJoinBySearch(search,pageNo,pageLimit);
        }

        if(deviceSnList.size() > 0){
            Conditions conditions = new Conditions(ChargingCable.class);
            conditions.and().in("deviceSn",deviceSnList);

            ChargingCable updateEntity = new ChargingCable();
            updateEntity.setState(ChargingCableEnum.State.Free.index());

            try {
                dao.updateNotNull(updateEntity,conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
    }

    @Override
    public boolean deleteByDeviceSn(String deviceSn) throws LogicException {
        try {
            return dao.deleteById(deviceSn) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }
}
